/*
 * Copyright (c) 2018.
 * This file was written by Fancyears·Milos·Malvis @connor. Any question/bug you can't post to 1243093366@qq.com.
 * ALL RIGHTS RESERVED.
 */
package org.fancyears.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author: Fancyears·Milos·Malvis
 * @CreateDate: 2019年1月10日 下午5:31:34
 * @Description:
 */

public class TargetProxy implements InvocationHandler {
	/**
	 * 代理对象
	 */
	private Object target;
	/** 拦截器接口 */
	private Interceptor interceptor;

	public TargetProxy(Object target, Interceptor interceptor) {
		this.target = target;
		this.interceptor = interceptor;
	}

	/**
	 * 将拦截逻辑封装到拦截器中，有客户端生成目标类的代理类的时候一起传入，这样客户端就可以设置不同的拦截逻辑。
	 * 
	 * @param target      生成的代理对象
	 * @param interceptor 拦截器接口
	 * @return
	 */
	/**
	 * @param target
	 * @param interceptor
	 * @return
	 */
	public static Object bind(Object target, Interceptor interceptor) {
		return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),
				new TargetProxy(target, interceptor));
	}

	// 在执行目标对象方法前加上自己的拦截逻辑
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		/** 执行客户端定义的拦截逻辑 ,拦截特定的方法 */
		MethodName methodName = this.interceptor.getClass().getAnnotation(MethodName.class);
		if (methodName == null || methodName.value() == null || methodName.value().length() <= 0)
			throw new NullPointerException(
					this.interceptor.getClass() + "上没有使用注解" + MethodName.class.getSimpleName() + "，需要定义拦截执行的方法名");
		/** 如果注解上的方法名和该方法名一样才拦截 */
		String name = methodName.value();
		if (name.equals(method.getName()))
			return interceptor.intercept(new Invocation(target, method, args));
		return method.invoke(this.target, args);
	}

}
